using System;
using Inputs;
using Modules.Game;
using UnityEngine;

namespace Modules.Camera
{
    /// <summary>
    ///     跟随摄像机
    /// </summary>
    public class FollowCamera : MonoBehaviour
    {
        /// <summary>
        ///     视角滚动最大距离
        /// </summary>
        private const float MaxScrollDistance = 20;

        /// <summary>
        ///     视角滚动最小距离
        /// </summary>
        private const float MinScrollDistance = 10;

        /// <summary>
        ///     视角横向移动距离
        /// </summary>
        private const float HMoveDistance = 30;

        /// <summary>
        ///     视角纵向移动距离
        /// </summary>
        private const float VMoveDistance = 40;

        /// <summary>
        ///     边缘移动速度
        /// </summary>
        private const float EdgeMoveSpeed = 20.0f;

        /// <summary>
        ///     鼠标移动边缘位置
        /// </summary>
        private const float EdgeSize = 0.0f;

        /// <summary>
        ///     当前视角垂直滚动速度
        /// </summary>
        private const float ScrollSpeed = 10.0f;

        /// <summary>
        ///     摄像机偏移位置
        /// </summary>
        private Vector3 _cameraOffsetPos;

        /// <summary>
        ///     摄像机跟随位置
        /// </summary>
        private Vector3 _followPos;

        /// <summary>
        ///     是否锁定视角
        /// </summary>
        private bool _locked;

        /// <summary>
        ///     当前视角垂直距离
        /// </summary>
        private float _scrollDistance;

        private void Awake()
        {
            MapInput.Instance.ResetAction += OnReset;
            MapInput.Instance.LockAction += OnLock;
        }

        // Start is called before the first frame update
        private void Start()
        {
            _followPos = GameModule.Instance.GetHeroPos();
            _cameraOffsetPos = UnityEngine.Camera.main!.transform.localPosition;
        }

        // Update is called once per frame
        private void Update()
        {
            CheckScrollView();
            CheckEdgeMove();
        }

        private void OnDestroy()
        {
            if (MapInput.IsExist)
            {
                MapInput.Instance.ResetAction -= OnReset;
                MapInput.Instance.LockAction -= OnLock;
            }
        }

        /// <summary>
        ///     检测垂直滚动
        /// </summary>
        private void CheckScrollView()
        {
            _scrollDistance = _cameraOffsetPos.magnitude;
            _scrollDistance -= Input.GetAxis("Mouse ScrollWheel") * ScrollSpeed;

            _scrollDistance = Math.Clamp(_scrollDistance, MinScrollDistance, MaxScrollDistance);

            _cameraOffsetPos = _cameraOffsetPos.normalized * _scrollDistance;

            UnityEngine.Camera.main!.transform.localPosition = _cameraOffsetPos;
        }

        /// <summary>
        ///     检测边缘移动
        /// </summary>
        private void CheckEdgeMove()
        {
            if (_locked)
            {
                _followPos = GameModule.Instance.GetHeroPos();
                transform.position = _followPos;
                return;
            }

            //屏幕左下角为坐标(0, 0)
            if (Input.mousePosition.x > Screen.width - EdgeSize) //如果鼠标位置在右侧
                _followPos.x += EdgeMoveSpeed * Time.deltaTime; //就向右移动

            if (Input.mousePosition.x < EdgeSize) _followPos.x -= EdgeMoveSpeed * Time.deltaTime;

            if (Input.mousePosition.y > Screen.height - EdgeSize) _followPos.z += EdgeMoveSpeed * Time.deltaTime;

            if (Input.mousePosition.y < EdgeSize) _followPos.z -= EdgeMoveSpeed * Time.deltaTime;

            // 距离限制
            if (_followPos.x < -HMoveDistance) _followPos.x = -HMoveDistance;
            if (_followPos.x > HMoveDistance) _followPos.x = HMoveDistance;

            if (_followPos.z < -VMoveDistance) _followPos.z = -VMoveDistance;
            if (_followPos.z > VMoveDistance) _followPos.z = VMoveDistance;

            transform.position = _followPos;
        }

        /// <summary>
        ///     重置位置
        /// </summary>
        private void OnReset()
        {
            Debug.Log("回到主角视角");
            _followPos = GameModule.Instance.GetHeroPos();
            transform.position = _followPos;
        }

        /// <summary>
        ///     切换锁定视角
        /// </summary>
        private void OnLock()
        {
            Debug.Log("锁定/解锁视角");
            _locked = !_locked;
        }
    }
}